公式
两球相交分为两种情况:
第一种 大球完全包围了小球
第二种 两球相交但无完全包含关系
第一种情况的答案是显而易见的,直接求出小球体积即可
下面给出第二种情况的求解方法
V
=
π
h
1
2
(
R
−
1
3
h
1
)
+
π
h
2
2
(
r
−
1
3
h
2
)
V = \pi h_1^2(R-\frac{1}{3}h_1) + \pi h_2^2(r-\frac{1}{3}h_2)
V=πh12(R−31h1)+πh22(r−31h2)
图中角
α
\alpha
α与角
β
\beta
β位置标反了(多谢评论区小伙伴的提醒)
推导
我们把相交部分面积分为两部分,一部分是大球刨出去的体积,一部分是小球抛出去的体积,并且这两部分面积计算公式相同。
接下来我们证明其中大球刨去体积的公式。
先做一些准备工作
cos
α
=
R
2
+
d
2
−
r
2
2
R
d
\cos\alpha = \frac{R^2+d^2-r^2}{2Rd}
cosα=2RdR2+d2−r2
h
1
=
R
−
R
c
o
s
α
h_1 = R-Rcos\alpha
h1=R−Rcosα
为了应用黎曼积分求体积,首先要得到大球被抛去部分的圆面面积公式。
由于刨去部分圆面的半径随着圆面的圆心从E点到F点的距离变小而变小,为了研究这两者间的关系,我们设圆面的圆心到F点的距离为
x
x
x 。
得到圆面半径的表达式为
R
2
−
(
R
c
o
s
α
+
x
)
2
)
\sqrt{R^2-(Rcos\alpha+x)^2})
R2−(Rcosα+x)2) ,从而圆面面积表达式为
π
(
R
2
−
(
R
c
o
s
α
+
x
)
2
)
\pi(R^2-(Rcos\alpha+x)^2)
π(R2−(Rcosα+x)2)
于是得到大球抛去体积
V
1
V_1
V1 的积分公式为
V
1
=
∫
0
h
1
π
(
R
2
−
(
R
c
o
s
α
+
x
)
2
)
d
x
V_1 = \int_0^{h_1}\pi(R^2-(Rcos\alpha+x)^2) dx
V1=∫0h1π(R2−(Rcosα+x)2)dx
经过一系列牛顿-莱布尼茨公式之后化简得到
V
1
=
π
(
−
1
3
h
1
2
−
R
h
1
2
c
o
s
α
+
R
2
h
1
s
i
n
2
α
)
V_1 = \pi(-\frac{1}{3}h_1^2-Rh_1^2cos\alpha+R^2h_1sin^ 2\alpha)
V1=π(−31h12−Rh12cosα+R2h1sin2α)
再把
c
o
s
α
cos\alpha
cosα 代入化简后得到
V
1
=
π
h
1
2
(
R
−
1
3
h
1
)
V_1 = \pi h_1^2(R-\frac{1}{3}h_1)
V1=πh12(R−31h1)
同理可得小球被刨去的体积
V
2
=
π
h
2
2
(
r
−
1
3
h
2
)
V_2 = \pi h_2^2(r-\frac{1}{3}h_2)
V2=πh22(r−31h2)
总体积
V
=
V
1
+
V
2
=
π
h
1
2
(
R
−
1
3
h
1
)
+
π
h
2
2
(
r
−
1
3
h
2
)
V = V_1 + V_2 = \pi h_1^2(R-\frac{1}{3}h_1) + \pi h_2^2(r-\frac{1}{3}h_2)
V=V1+V2=πh12(R−31h1)+πh22(r−31h2)
代码
话不多说,上代码
#include<iostream>
#include<cmath>
#define Pi 3.14
using namespace std;
class Sphere //属性分别为:(x,y,z)三个坐标以及半径
{
private:
double m_x;
double m_y;
double m_z;
double m_r;
public:
Sphere():m_x(0),m_y(0), m_z(0), m_r(0)
{
}
Sphere(double x,double y,double z,double r) :m_x(x), m_y(y), m_z(z), m_r(r)
{
}
double getx();
double gety();
double getz();
double getr();
void modi_x(double x);
void modi_y(double y);
void modi_z(double z);
void modi_r(double r);
bool intersect(Sphere& o);
double vol_ints(Sphere& o);
double distance(Sphere& o);
};
//获得属性
double Sphere::getx()
{
return m_x;
}
double Sphere::gety()
{
return m_y;
}
double Sphere::getz()
{
return m_z;
}
double Sphere::getr()
{
return m_r;
}
//修改属性
void Sphere::modi_x(double x)
{
m_x = x;
}
void Sphere::modi_y(double y)
{
m_y = y;
}
void Sphere::modi_z(double z)
{
m_z = z;
}
void Sphere::modi_r(double r)
{
m_r = r;
}
//判断两个球是否相交
bool Sphere::intersect(Sphere& o)
{
if (m_x == o.m_x && m_y == o.m_y && m_z == o.m_z)
return true;
else
{
double dis = distance(o);
if ((m_r + o.m_r) * (m_r + o.m_r) > dis)
return true;
else
return false;
}
}
//计算两球圆心之间的距离
double Sphere::distance(Sphere& o)
{
return (m_x - o.m_x) * (m_x - o.m_x) + (m_y - o.m_y) * (m_y - o.m_y) + (m_z - o.m_z) * (m_z - o.m_z);
}
//计算两球相交部分体积
double Sphere::vol_ints(Sphere& o)
{
if (!intersect(o))
return 0;
else
{
double dis = distance(o);
double max = m_r > o.m_r ? m_r : o.m_r;
double min = m_r > o.m_r ? o.m_r : m_r;
if (sqrt(dis) + min <= max)
return 4 / 3 * Pi * pow(min, 3);
else
{
double cos_a = (max * max + dis * dis - min * min) / (2 * max * dis);
double cos_b = (min * min + dis * dis - max * max) / (2 * min * dis);
double h_a = max * (1 - cos_a);
double h_b = min * (1 - cos_b);
return (Pi / 3) * (3 * max - h_a) * h_a * h_a + (Pi / 3) * (3 * min - h_b) * h_b * h_b;
}
}
}
第一次写文章,发现错误的话请各位多多指教